﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Mvc.XForms.Examples.Repository;
using Mvc.XForms.Examples.Model;
using System.Web.Mvc;
using Mvc.XForms.Utilities;
using Mvc.XForms.Examples;

namespace Mvc.XForms.Tests.XFormsTests {
	[TestClass]
	public class DeserializerTests {
		private IRepository<Address> addressRepostiory;
		private IRepository<Customer> customerRepostiory;

		[TestInitialize]
		public void Setup() {
			var db = new InMemoryDataContext();
			addressRepostiory = new InMemoryRepository<Address>(db);
			customerRepostiory = new InMemoryRepository<Customer>(db);
		}

		[TestMethod]
		public void Can_deserialize_simple_properties() {
			var customer = customerRepostiory.Get(1);
			var form = new FormCollection();
			var modelState = new ModelStateDictionary();

			form.Add("Name", "Joe Bloggs");
			form.Add("Faction", "Republic");
			form.Add("IsActive", "false");
			form.Add("DateOfBirth", "27/02/1978");
			var ds = new TestDeserializer(modelState);
			ds.Deserialize(customer, form);

			Assert.AreEqual("Joe Bloggs", customer.Name);
			Assert.AreEqual(Faction.Republic, customer.Faction);
			Assert.IsFalse(customer.IsActive);
			Assert.AreEqual(Convert.ToDateTime("27/02/1978"), customer.DateOfBirth);
		}

		[TestMethod]
		public void Can_deserialize_select_for_simple_type() {
			var customer = customerRepostiory.Get(1);
			var form = new FormCollection();
			var modelState = new ModelStateDictionary();

			form.Add("Notes", "");
			form.Add("Notes", "Note 1");
			form.Add("Notes", "Note 2");
			var ds = new TestDeserializer(modelState);
			ds.Deserialize(customer, form);

			Assert.AreEqual("Note 2", customer.Notes[1]);
			Assert.AreEqual(2, customer.Notes.Count);
		}

		[TestMethod]
		public void Deserialize_empty_select_clears_list() {
			var customer = customerRepostiory.Get(1);
			var form = new FormCollection();
			var modelState = new ModelStateDictionary();

			Assert.AreEqual(1, customer.Notes.Count);

			form.Add("Notes", "");
			var ds = new TestDeserializer(modelState);
			ds.Deserialize(customer, form);

			Assert.AreEqual(0, customer.Notes.Count);
		}

		[TestMethod]
		public void Can_deserialize_select_for_complex_type() {
			var customer = customerRepostiory.Get(1);
			var form = new FormCollection();
			var modelState = new ModelStateDictionary();

			form.Add("Mailinglists", "ID");
			form.Add("Mailinglists", "1");
			form.Add("Mailinglists", "2");
			form.Add("Mailinglists", "4");
			var ds = new TestDeserializer(modelState);
			ds.Deserialize(customer, form);

			Assert.AreEqual(4, customer.MailingLists[2].ID);
			Assert.AreEqual(3, customer.MailingLists.Count);
		}

		[TestMethod]
		public void Can_deserialize_repeat_for_non_IEntity_complex_object() {
			var customer = customerRepostiory.Get(1);
			var form = new FormCollection();
			var modelState = new ModelStateDictionary();

			form.Add("Orders-", "");
			form.Add("Orders-0_ID", "1");
			var ds = new TestDeserializer(modelState);
			ds.Deserialize(customer, form);

			Assert.AreEqual(4, customer.MailingLists[2].ID);
			Assert.AreEqual(3, customer.MailingLists.Count);
		}

		[TestMethod]
		public void Deserialize_empty_repeat_clears_list() {
			throw new NotImplementedException();
		}

		[TestMethod]
		public void Deserialize_child_IEntity_with_ID_in_form_should_update_repository_address() {
			var customer = customerRepostiory.Get(1);
			var form = new FormCollection();
			var modelState = new ModelStateDictionary();

			form.Add("Address_ID", "1");
			form.Add("Address_Address1", "New address 1");
			form.Add("Address_Planet_ID", "1");
			var ds = new TestDeserializer(modelState);
			ds.Deserialize(customer, form);

			var address = addressRepostiory.Get(1);
			Assert.AreEqual("New address 1", customer.Address.Address1);
			Assert.AreEqual("Alderaan", customer.Address.Planet.Name);
		}

		[TestMethod]
		public void Deserialize_child_IEntity_without_ID_in_form_should_add_address_to_repository() {
			var customer = customerRepostiory.Get(1);
			var addressesCount = addressRepostiory.AsQueryable().Count();
			var form = new FormCollection();
			var modelState = new ModelStateDictionary();

			form.Add("Address_Address1", "New address 1");
			form.Add("Address_Planet_ID", "1");
			var ds = new TestDeserializer(modelState);
			ds.Deserialize(customer, form);

			var addresses = addressRepostiory.AsQueryable().ToList();

			Assert.AreEqual(addressesCount + 1, addresses.Count);
			Assert.AreEqual("New address 1", addresses.Last().Address1);
		}

		[TestMethod]
		public void Can_deserialize_select_input_for_IEntity() {
			var customer = customerRepostiory.Get(1);
			var form = new FormCollection();
			var modelState = new ModelStateDictionary();

			form.Add("Mailinglists", "ID");
			form.Add("Mailinglists", "1");
			form.Add("Mailinglists", "2");
			form.Add("Mailinglists", "4");
			var ds = new TestDeserializer(modelState);
			ds.Deserialize(customer, form);

			Assert.AreEqual("Dark-side News", customer.MailingLists[0].Name);
			Assert.AreEqual(3, customer.MailingLists.Count);
		}
	}
}
